#include <string>
#include <iostream>

#include <app/modules/Asound.h>

Asound::Asound ( std::string filename, Source &source, Listener &listener ) {
    
    //initiliazing OpenAL
    this -> device = alcOpenDevice ( NULL );
    this -> context = alcCreateContext ( this -> device, NULL );
    this -> source = &source;
    this -> listener = &listener;
    
    //check for errors
    if ( !this -> device ) {
        std::cerr << "Error open device!" << std::endl;
    }
    if ( !alcMakeContextCurrent ( this -> context ) ) {
        std::cerr << "Error creating context!" << std::endl;
    }
    
    //configuring listener
    alListenerfv ( AL_POSITION, listener.attributes.position );
    alListenerfv ( AL_ORIENTATION, listener.attributes.orientation );
    alListenerfv ( AL_VELOCITY, listener.attributes.velocity );
    
    //source generation
    alGenSources ( (ALuint) 1, &source.source );
    
    alSourcef ( this -> source -> source, AL_PITCH, 1 );
    alSourcef ( this -> source -> source, AL_GAIN, 1 );
    alSourcefv ( this -> source -> source, AL_POSITION, source.attributes.position );
    alSourcefv ( this -> source -> source, AL_VELOCITY, source.attributes.velocity );
    alSourcei ( this -> source -> source, AL_LOOPING, AL_FALSE );
    
    //buffer generation
    alGenBuffers ( (ALuint) 1, &this -> source -> buffer );
    
    //loading an audio stream to a buffer
    alutLoadWAVFile ( (ALbyte*) filename.c_str (), 
                      &source.format,
                      &source.data,
                      &source.size,
                      &source.freq,
                      &source.loop
                    );
    
    alBufferData ( source.buffer, source.format, source.data, source.size, source.freq );
    
    //binding source to a buffer
    alSourcei ( this -> source -> source, AL_BUFFER, this -> source -> buffer );
}

void Asound::play () {
    
    alSourcePlay ( this -> source -> source );
    
    alGetSourcei ( this -> source -> source, AL_SOURCE_STATE, &this -> source -> state );
    
    while ( this -> source -> state == AL_PLAYING ) {
        alGetSourcei ( this -> source -> source, AL_SOURCE_STATE, &this -> source -> state );
    }
}

void Asound::pause () {
    //
}

Asound::~Asound () {
    //clean up context
    alDeleteSources ( 1, &this -> source -> source );
    alDeleteBuffers ( 1, &this -> source -> buffer );
    device = alcGetContextsDevice ( this -> context );
    alcMakeContextCurrent ( NULL );
    alcDestroyContext ( this -> context );
    alcCloseDevice ( this -> device );
}
